#include "mysocket.h"

pthread_mutex_t g_db_mutex = PTHREAD_MUTEX_INITIALIZER;

/*========================<信号处理>========================*/
void set_signal_handle(int sig)
{
    struct sigaction act;
    act.sa_flags = SA_RESTART;
    act.sa_handler = sig_handler;
    sigemptyset(&act.sa_mask);

    sigaction(sig, &act, NULL);
}

void sig_handler(int sig)
{
    if (sig == SIGCHLD)
    {
        pid_t pid;
        while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
        {
            printf("子进程 %d 结束，有一个客户端已断开连接\n", pid);
        }
    }
}

/*========================<网络连接>========================*/
int CreateSocket()
{
    int fd;
    int ret;
    Addr_in serverSock;

    /*创建套接字*/
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0)
        ErrExit("socket");

    /*允许地址快速重用*/
    int flag = 1;
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)))
        perror("setsockopt");

    /*绑定地址*/
    serverSock.sin_family = AF_INET;
    serverSock.sin_port = htons(SERVER_PORT);
    ret = inet_pton(AF_INET, SERVER_LISTEN_IP, &serverSock.sin_addr);
    if (ret <= 0)
    {
        if (ret == 0)
            fprintf(stderr, "无效的IP地址格式\n");
        ErrExit("inet_pton");
    }
    ret = bind(fd, (Addr*)&serverSock, sizeof(serverSock));
    if (ret < 0)
        ErrExit("bind");

    /*监听客户端*/
    ret = listen(fd, BACKLOG);
    if (ret < 0)
        ErrExit("listen");

    return fd;
}

/*========================<数据库操作>========================*/
//-2解析字符串失败 -1操作数据库失败
int recv_to_Send(const char* recv_buffer, size_t recv_size, char* send_buffer, size_t send_size)
{
    char* tokens[MAX_TOKEN_NUM] = { NULL };
    int token_count = 0;

    token_count = string_format(recv_buffer, tokens, MAX_TOKEN_NUM, " ,|");
    if (token_count == 0)
    {
        snprintf(send_buffer, send_size, "字符串解析失败");
        return -2;
    }

    sqlite3* db;
    db = mysql_open(DATABASE_NAME);

    if (strcmp(tokens[0], "1") == 0)
    {
        if (token_count >= 2)
        {
            if (mysql_create(db, tokens[1]) == 0)
                snprintf(send_buffer, send_size, "创建表%s成功", tokens[1]);
            else
                snprintf(send_buffer, send_size, "创建表%s失败", tokens[1]);
        }
        else
        {
            snprintf(send_buffer, send_size, "输入错误 使用方法: 1 <数据表名称>");
        }
    }
    else if (strcmp(tokens[0], "2") == 0)
    {
        if (token_count >= 6)
        {
            dataStruct tmpData;
            tmpData.id = atoi(tokens[2]);
            snprintf(tmpData.name, sizeof(tmpData.name), "%s", tokens[3]);
            snprintf(tmpData.sex, sizeof(tmpData.sex), "%s", tokens[4]);
            tmpData.score = atoi(tokens[5]);

            if (mysql_insert(db, tokens[1], tmpData) == 0)
                snprintf(send_buffer, send_size, "数据表%s添加%s同学成功", tokens[1], tokens[3]);
            else
                snprintf(send_buffer, send_size, "数据表%s添加%s同学失败", tokens[1], tokens[3]);
        }
        else
        {
            snprintf(send_buffer, send_size, "输入错误 使用方法: 2 <数据表名字> <ID> <名字> <性别> <成绩>");
        }
    }
    else if (strcmp(tokens[0], "3") == 0)
    {
        if (token_count >= 3)
        {
            if (mysql_delete_name(db, tokens[1], tokens[2]) == 0)
                snprintf(send_buffer, send_size, "数据表%s删除%s同学成功", tokens[1], tokens[2]);
            else
                snprintf(send_buffer, send_size, "数据表%s删除%s同学失败", tokens[1], tokens[2]);
        }
        else
        {
            snprintf(send_buffer, send_size, "输入错误 使用方法: 3 <数据表名字> <要删除的学生的姓名>");
        }
    }
    else if (strcmp(tokens[0], "4") == 0)
    {
        if (token_count >= 4)
        {
            if (mysql_update(db, tokens[1], tokens[2], atoi(tokens[3])) == 0)
                snprintf(send_buffer, send_size, "将数据表%s中%s同学成绩改为%s成功", tokens[1], tokens[2], tokens[3]);
            else
                snprintf(send_buffer, send_size, "将数据表%s中%s同学成绩改为%s失败", tokens[1], tokens[2], tokens[3]);
        }
        else
        {
            snprintf(send_buffer, send_size, "输入错误 使用方法: 4 <数据表名字> <要修改学生成绩的姓名> <新成绩>");
        }
    }
    else if (strcmp(tokens[0], "5") == 0)
    {
        if (token_count >= 3)
        {
            dataStruct tmpdata;
            tmpdata = mysql_find(db, tokens[1], tokens[2]);
            if (tmpdata.id == -1)
                snprintf(send_buffer, send_size, "数据表%s中查找不到%s同学的信息", tokens[1], tokens[2]);
            else
                snprintf(send_buffer, send_size, "数据表%s中%s同学的信息为: ID:%d 姓名:%s 性别:%s 成绩:%d", tokens[1], tokens[2],tmpdata.id,tmpdata.name,tmpdata.sex,tmpdata.score);
        }
        else
        {
            snprintf(send_buffer, send_size, "输入错误 使用方法: 5 <数据表名字> <要查找的学生的姓名>)");
        }
    }
    else
    {
        snprintf(send_buffer, send_size, "无法识别你的操作");
    }

    mysql_close(db);
    for (int i = 0;i < token_count;i++)
        free(tokens[i]);
    return 0;
}

/**
 * 将输入字符串按指定分隔符分割并存储到token数组中
 * @param input 输入的原始字符串
 * @param token 用于存储分割后子串的指针数组
 * @param max_tokens token数组的最大容量
 * @param delimiters 指定的分隔符字符串
 * @return 实际分割得到的子串数量
 */
int string_format(const char* input, char* token[], int max_tokens, const char* delimiters)
{
    if (input == NULL || token == NULL || max_tokens <= 0)
        return 0;

    const char* start = input;//子串的起始
    int count = 0;
    bool token_end_flag = false;//是不是字串的末尾

    // 处理字符串中的分隔符情况
    while (*input != '\0' && max_tokens > count)
    {
        if (strchr(delimiters, *input))//如果是分隔符
        {
            if (!token_end_flag)
            {
                // 分配内存并保存当前子串
                size_t len = input - start;
                token[count] = (char*)malloc(sizeof(char) * (len + 1));
                if (token[count] == NULL)
                {
                    perror("malloc");
                    break;
                }
                strncpy(token[count], start, len);
                token[count][len] = '\0';
                count++;
                token_end_flag = true;
            }
            input++;
        }
        else
        {
            if (token_end_flag)
            {
                start = input;
                token_end_flag = false;
            }
            input++;
        }
    }

    /*处理最后一个子串*/
    if (*input == '\0' && count < max_tokens)
    {
        size_t len = input - start;
        token[count] = malloc(sizeof(char) * (len + 1));
        if (token[count] == NULL)
        {
            perror("malloc");
        }
        else
        {
            strncpy(token[count], start, len);
            token[count][len] = '\0';
            count++;
        }
    }
    return count;
}
